package com.djh.security.config;

import com.djh.security.handle.AuthExceptionEntryPoint;
import com.djh.security.handle.CustomAccessDeniedHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 资源服务器配置
 *
 * @author qipp
 * @date 2020/1/9 12:11
 * @since 1.0.1
 */

@ConditionalOnProperty(prefix = SecurityProperties.PREFIX,value = "type",havingValue = "resourceServer")
@Slf4j
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    /**
     * 角色/权限 分隔符{@value}
     */
    private final static String TO = "2";

    /**
     * 无需授权即可访问的接口{@value}
     */
    private final static String UN_AUTHENTICATED = "unAuthenticated";

    /**
     * 指定角色{@value}
     */
    private final static String ROLE = "role";

    /**
     * 指定权限{@value}
     */
    private final static String AUTH = "auth";

    /**
     * 权限不足处理器
     */
    private final CustomAccessDeniedHandler customAccessDeniedHandler;

    /**
     * 注入配置的tokenStore
     */
    private final TokenStore tokenStore;

    /**
     * 用来解决匿名用户访问无权限资源时的异常
     */
    private final AuthExceptionEntryPoint authExceptionEntryPoint;






    private final SecurityProperties properties;

    public ResourceServerConfig(
            CustomAccessDeniedHandler customAccessDeniedHandler,
            TokenStore tokenStore,
            AuthExceptionEntryPoint authExceptionEntryPoint,
            SecurityProperties properties) {
        this.customAccessDeniedHandler = customAccessDeniedHandler;
        this.tokenStore = tokenStore;
        this.authExceptionEntryPoint = authExceptionEntryPoint;
        this.properties = properties;
    }


    /**
     * 资源服务配置
     *
     * @param resources 资源服务
     * @author qipp
     * @date 2020/1/10 17:47
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        // 资源服务Id（简易配置文件形式管理）
        resources.resourceId(properties.getClient())
                // 设置tokenStore
                .tokenStore(tokenStore).stateless(true)
                // 用来解决匿名用户访问无权限资源时的异常
                .authenticationEntryPoint(authExceptionEntryPoint);
    }

    /**
     * 配置资源拦截规则
     *
     * @param http 请求规则
     * @author qipp
     * @date 2020/1/10 17:10
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);

        // 设置不受保护路径 设置受保护路径需要的角色权限（某司姓老师贡献的）
        Map<String, List<String>> antMatchers = properties.getAntMatchers();
        if (antMatchers != null) {
            Set<String> keys = antMatchers.keySet();
            for (String key : keys) {
                if (key.equals(UN_AUTHENTICATED)) {
                    List<String> urls = antMatchers.get(key);
                    for (String url : urls) {
                        http.authorizeRequests().antMatchers(url).permitAll();
                    }
                }else{
                    String type = key.split(TO)[0];
                    String str = key.split(TO)[1];
                    List<String> urls = antMatchers.get(key);
                    if (type.equals(ROLE)) {
                        for (String url : urls) {
                            http.authorizeRequests().antMatchers(url).hasRole(str);
                        }
                    }
                    if (type.equals(AUTH)) {
                        for (String url : urls) {
                            http.authorizeRequests().antMatchers(url).hasAuthority(str);
                        }
                    }
                }
            }
        }

        // 配合测试的代码
        // /save/no不受保护
        // /user/save 受保护
        http.authorizeRequests()
                .antMatchers("/save/**").permitAll()
                .anyRequest().authenticated();

        // 权限不足处理器
        http.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);
        
        // todo 动态权限动态scope存在问题后续会进行解决
//        // 如果开启动态权限 或者开启动态作用域
//        if(surgeOauth2Properties.isEnableDynamicAuth() || (surgeOauth2Properties.isEnableDynamicScopeAuth()) && surgeOauth2Properties.scopeRuleIsExist() ){
//            // 动态url权限
//            http.authorizeRequests().withObjectPostProcessor(new DefinedObjectPostProcessor());
//        }
    }


}
